package br.com.medvagas.negocio.facade.p;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.apache.commons.lang.RandomStringUtils;
import org.hibernate.Hibernate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import br.com.medvagas.comum.entidade.EsperienciaProfissional;
import br.com.medvagas.comum.entidade.FormacaoAcademicaTitulacao;
import br.com.medvagas.comum.entidade.FormacaoComplementar;
import br.com.medvagas.comum.entidade.LinguaEstrangeira;
import br.com.medvagas.comum.entidade.ParticipacaoEvento;
import br.com.medvagas.comum.entidade.UsuarioDescadastrado;
import br.com.medvagas.comum.entidade.UsuarioProfissional;
import br.com.medvagas.comum.entidade.Vaga;
import br.com.medvagas.comum.entidade.VagaUsuarioProfissional;
import br.com.medvagas.comum.entidade.vo.VOConsultaVaga;
import br.com.medvagas.comum.excecao.ExcecaoRegraNegocio;
import br.com.medvagas.comum.util.UtilCriptografia;

@Service
public class ManterProfissional implements IManterProfissional {

	@PersistenceContext
	private EntityManager em;
	
	@Override
	@Transactional
	public UsuarioProfissional cadastrar(UsuarioProfissional up) {

		// valida cadastro de 2 emails iguais
		Query query = em.createNamedQuery("UsuarioProfissional.consultarPorEmail");
		query.setParameter("email", up.getEmail());
		List<?>  lsIdUsuarioProfissional = query.getResultList();
		if (!lsIdUsuarioProfissional.isEmpty()) {
			throw new ExcecaoRegraNegocio("MSG_0004");
		}
		
		// valida cadastro de 2 CPFs iguais
		query = em.createNamedQuery("UsuarioProfissional.consultarPorCpf");
		query.setParameter("cpf", up.getCpf());
		lsIdUsuarioProfissional = query.getResultList();
		if (!lsIdUsuarioProfissional.isEmpty()) {
			throw new ExcecaoRegraNegocio("MSG_0005");
		}

		//FIXME tirar esse codigo fixo, deve virar campo na tela de cadastro
		up.getEndereco().setPais("Brasil");
		em.persist(up.getEndereco());
		
		String tokenValidacaoEmail = RandomStringUtils.randomAlphanumeric(10);
		up.setTokenValidacaoEmail(tokenValidacaoEmail);
		up.setUsuarioValidado(Boolean.FALSE);
		up.setDataCadastro(new Date());
		up.setSenha(UtilCriptografia.criptografarSha(up.getSenha()));
		up.setConhecimentoMsexcel(Boolean.FALSE);
		up.setConhecimentoMsword(Boolean.FALSE);
		up.setConhecimentoMspowerpoint(Boolean.FALSE);
		
		em.persist(up);

		// TODO enviar email
		
		return up;
	}

	@Override
	@Transactional
	public UsuarioProfissional alterar(UsuarioProfissional up) {
		em.merge(up.getEndereco());
		up.setDataUltimaAlteracao(new Date());
		em.merge(up);
		return up;
	}
	
	@Override
	@Transactional(readOnly=true)
	public UsuarioProfissional consultarPorId(Integer idUsuarioProfissional) {
		UsuarioProfissional up = em.find(UsuarioProfissional.class, idUsuarioProfissional);
		Hibernate.initialize(up.getEndereco());
		return up;
	}	
	
	@Override
	@Transactional(readOnly=true)
	public List<UsuarioProfissional> consultarTodos() {
		TypedQuery<UsuarioProfissional> query = em.createNamedQuery("UsuarioProfissional.consultarTodos", UsuarioProfissional.class);
		return query.getResultList();
	}	
	
	@Override
	@Transactional
	public void alterarSenha(Integer idUsuarioProfissional, String senhaAtual,	String senhaNova) {
		UsuarioProfissional up = em.find(UsuarioProfissional.class, idUsuarioProfissional);
		String senhaAtualCripto = UtilCriptografia.criptografarSha(senhaAtual);
		if (!senhaAtualCripto.equals(up.getSenha())) {
			throw new ExcecaoRegraNegocio("MSG_0006");
		}
		String novaSenhaCripto = UtilCriptografia.criptografarSha(senhaNova);
		up.setSenha(novaSenhaCripto);
		up.setDataUltimaAlteracao(new Date());
		em.merge(up);
	}

	@Override
	@SuppressWarnings("unchecked")
	@Transactional(readOnly=true)
	public List<VOConsultaVaga> pesquisarVaga(Vaga vaga, Integer idUsuarioProfissional) {
		Query query = em.createNamedQuery("Vaga.pesquisarVaga");
		query.setParameter("ativa", Boolean.TRUE);
		query.setParameter("idUsuarioProfissional", idUsuarioProfissional);
		query.setParameter("idProfissao", vaga.getIdProfissao());
		query.setParameter("idEspecialidade", vaga.getIdEspecialidade());
		List<VOConsultaVaga> lsVaga = query.getResultList();
		return lsVaga;
	}
	
	@Override
	@SuppressWarnings("unchecked")
	@Transactional(readOnly=true)
	public List<VOConsultaVaga> consultarVagaCandidato(Integer idUsuarioProfissional) {
		Query query = em.createNamedQuery("Vaga.consultarVagaCandidato");
		query.setParameter("ativa", Boolean.TRUE);
		query.setParameter("idUsuarioProfissional", idUsuarioProfissional);
		List<VOConsultaVaga> lsVaga = query.getResultList();
		return lsVaga;
	}

	@Override
	@Transactional
	public void candidatar(VagaUsuarioProfissional vup) {
		vup.setData(new Date());
		em.persist(vup);
	}

	@Override
	@Transactional(readOnly=true)
	public UsuarioProfissional consultarCurriculo(Integer idUsuarioProfissional) {
		TypedQuery<UsuarioProfissional> query = 
				em.createNamedQuery("UsuarioProfissional.consultarCurriculo", UsuarioProfissional.class);
		query.setParameter("idUsuarioProfissional", idUsuarioProfissional);
		return query.getSingleResult();
	}

	@Override
	@Transactional
	public void addFormacaoAcademica(FormacaoAcademicaTitulacao formacaoAcademica) {
		em.persist(formacaoAcademica);
	}
	
	@Override
	@Transactional
	public void excluirFormacaoAcademica(Integer idFormacaoAcademicaTitulacao) {
		Query query = em.createNamedQuery("FormacaoAcademicaTitulacao.delete");
		query.setParameter("idFormacaoAcademicaTitulacao", idFormacaoAcademicaTitulacao);
		query.executeUpdate();
	}
	
	@Override
	@Transactional
	public void addFormacaoComplementar(FormacaoComplementar formacaoComplementar) {
		em.persist(formacaoComplementar);
	}
	
	@Override
	@Transactional
	public void excluirFormacaoComplementar(Integer idFormacaoComplementar) {
		Query query = em.createNamedQuery("FormacaoComplementar.delete");
		query.setParameter("idFormacaoComplementar", idFormacaoComplementar);
		query.executeUpdate();
	}
	
	@Override
	@Transactional
	public void addParticipacaoEvento(ParticipacaoEvento participacaoEvento) {
		em.persist(participacaoEvento);
	}
	
	@Override
	@Transactional
	public void excluirParticipacaoEvento(Integer idParticipacaoEvento) {
		Query query = em.createNamedQuery("ParticipacaoEvento.delete");
		query.setParameter("idParticipacaoEvento", idParticipacaoEvento);
		query.executeUpdate();
	}
	
	@Override
	@Transactional
	public void addEsperienciaProfissional(EsperienciaProfissional esperienciaProfissional) {
		em.persist(esperienciaProfissional);
	}
	
	@Override
	@Transactional
	public void excluirEsperienciaProfissional(Integer idEsperienciaProfissional) {
		Query query = em.createNamedQuery("EsperienciaProfissional.delete");
		query.setParameter("idEsperienciaProfissional", idEsperienciaProfissional);
		query.executeUpdate();
	}
	
	@Override
	@Transactional
	public void addLinguaEstrangeira(LinguaEstrangeira linguaEstrangeira) {
		em.persist(linguaEstrangeira);
	}
	
	@Override
	@Transactional
	public void excluirLinguaEstrangeira(Integer idLinguaEstrangeira) {
		Query query = em.createNamedQuery("LinguaEstrangeira.delete");
		query.setParameter("idLinguaEstrangeira", idLinguaEstrangeira);
		query.executeUpdate();
	}
	
	@Override
	@Transactional
	public void alterarConhecimentoInformativa(Integer idUsuarioProfissional, Boolean msExcel, Boolean msPowerpoint, Boolean msWord) {
		StringBuilder sql = new StringBuilder();
		sql.append("update usuario_profissional set");
		if (msExcel != null) {
			sql.append(" conhecimento_msexcel = :conhecimento_msexcel");
		}
		if (msPowerpoint != null) {
			sql.append(" conhecimento_mspowerpoint = :conhecimento_mspowerpoint");
		}
		if (msWord != null) {
			sql.append(" conhecimento_msword = :conhecimento_msword");
		}
		sql.append(" where id_usuario_profissional = :idUsuarioProfissional");
		
		Query query = em.createNativeQuery(sql.toString());
		
		if (msExcel != null) {
			query.setParameter("conhecimento_msexcel", msExcel);
		}
		if (msPowerpoint != null) {
			query.setParameter("conhecimento_mspowerpoint", msPowerpoint);
		}
		if (msWord != null) {
			query.setParameter("conhecimento_msword", msWord);
		}
		query.setParameter("idUsuarioProfissional", idUsuarioProfissional);
		
		query.executeUpdate();
	}

	@Override
	@Transactional
	public void descadastrar(UsuarioDescadastrado usuarioDescadastrado) {
		usuarioDescadastrado.setData(new Date());
		em.persist(usuarioDescadastrado);
		
		Query query = em.createNamedQuery("UsuarioProfissional.delete");
		query.setParameter("idUsuarioProfissional", usuarioDescadastrado.getIdAntigoUsuario());
		query.executeUpdate(); // cascade_delete nos relacionamentos via banco
	}
	
	@Override
	@Transactional
	public void excluirUsuario(Integer idUsuarioProfissional) {
		Query query = em.createNamedQuery("UsuarioProfissional.delete");
		query.setParameter("idUsuarioProfissional", idUsuarioProfissional);
		query.executeUpdate();
	}
	
}
